# -*- coding: utf8 -*-

import psutil
import os
import lorun

from multiprocessing import Pool
from utils import ProblemIOMode

def _run(instance, arg):
    in_put, out_put = arg
    return instance._run_one(in_put, out_put)

class JudgeClient(object):
  def __init__(self, run_config, work_dir, io_mode, test_case_path,
               in_file, out_file, is_spj):

    self._run_config = run_config
    self._work_dir = work_dir
    self._io_mode = io_mode
    self._test_case_path = test_case_path
    self._in_file = in_file
    self._out_file = out_file
    self._is_spj = is_spj
  
  def _run_one(self, in_put, out_put):
    if self._io_mode == ProblemIOMode.standard:
      fin = open(in_put)
      out_file = os.path.join(self._work_dir, 'temp.out')
      ftemp = open(out_file, 'w')
      self._run_config['fd_in'] = fin.fileno()
      self._run_config['fd_out'] = ftemp.fileno()
    else:
      in_file_path = os.path.join(self._work_dir, self._in_file)
      out_file = os.path.join(self._work_dir, self._out_file)
      os.system('cp %s %s'%(in_put, in_file_path))
    
    rst = lorun.run(self._run_config)
    if rst['result'] == 0:
      if self._is_spj:
        spj = os.path.join(self._work_dir, 'spj')
        crst = os.system('%s %s %s %s'%(spj, in_put, out_file, out_put))
      else:
        ftemp = open(out_file)
        fout = open(out_put)
        crst = lorun.check(fout.fileno(), ftemp.fileno())
        fout.close()
        ftemp.close()
      if crst != 0:
        rst['result'] = crst
    return rst
  
  def run(self):
    files = os.listdir(self._test_case_path)
    test_case_list = []
    ans = ''
    for file in files:
      if file.find('in') != -1:
        test_case_list.append(file)
      elif file.find('ans') != -1:
        ans = 'ans'
      elif file.find('out') != -1:
        ans = 'out'
    
    result = []
    test_case_list.sort(key=lambda x: (len(x), x))
    test_case_id = 1
    pool = Pool(processes=psutil.cpu_count())
    for test_case in test_case_list:
      in_put = os.path.join(self._test_case_path, test_case)
      out_put = os.path.join(self._test_case_path, test_case.replace('in', ans))
      if os.path.isfile(in_put) and os.path.isfile(out_put):
        arg = in_put, out_put
        tmp = pool.apply_async(_run, (self, arg)).get()
        tmp['test_case'] = test_case
        tmp['test_case_id'] = test_case_id
        result.append(tmp)
        test_case_id += 1
        
    pool.close()
    pool.join()

    return result
  
  def __getstate__(self):
    # http://stackoverflow.com/questions/25382455/python-notimplementederror-pool-objects-cannot-be-passed-between-processes
    self_dict = self.__dict__.copy()
    return self_dict